﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Core;
using Windows.Foundation.Diagnostics;
using Windows.Storage;

namespace JiveMessenger.Log
{
    public class Logger
    {
        private Task _errorHandlerTask;
        private readonly object LockObject = new object();
        public LoggingChannel logChannel;

        public LoggingSession logSession;

        private StorageFolder logUploadFolder;

        public const string LOG_SESSION_RESROUCE_NAME = "LogSession";

        static private Logger logger;
        private const int DAYS_TO_DELETE = 15;

        public async Task InitiateLogger()
        {

            logChannel = new LoggingChannel("JiveMessengerLogChannel");
            logSession = new LoggingSession("JiveMessengerLogSession");

            logSession.AddLoggingChannel(logChannel);

            await RegisterUnhandledErrorHandler();
        }

        /// <summary> 
        /// Maintains singleton object  
        /// </summary> 
        /// <returns></returns> 
        static public Logger GetLogger()
        {
            if (logger == null)
            {
                logger = new Logger();
            }
            return logger;
        }

        public void ErrorException(string message, Exception ex)
        {
            if (DesignMode.DesignModeEnabled || this.logChannel == null)
                return;
            this.logChannel.LogMessage(message + ":\r\n" + ex.ToString(), LoggingLevel.Error);
            SaveFile();
        }
        public void Error(string message)
        {
            if (DesignMode.DesignModeEnabled || this.logChannel == null)
                return;
            this.logChannel.LogMessage(message, LoggingLevel.Error);
        }
        public void Info(string message)
        {
            if (DesignMode.DesignModeEnabled || this.logChannel == null)
                return;
            this.logChannel.LogMessage(message, LoggingLevel.Information);
            SaveFile();
        }
        public void Info(string message, params object[] parameters)
        {
            if (DesignMode.DesignModeEnabled || this.logChannel == null)
                return;
            this.logChannel.LogMessage(string.Format(message, parameters), LoggingLevel.Information);
            SaveFile();
        }
        public void Debug(string message)
        {
            if (DesignMode.DesignModeEnabled || this.logChannel == null)
                return;
            this.logChannel.LogMessage(message, LoggingLevel.Verbose);
            SaveFile();
        }
        public void Debug(string message, params object[] parameters)
        {
            if (DesignMode.DesignModeEnabled || this.logChannel == null)
                return;
            this.logChannel.LogMessage(string.Format(message, parameters), LoggingLevel.Verbose);
            SaveFile();
        }
        public void Warn(string message)
        {
            if (DesignMode.DesignModeEnabled || this.logChannel == null)
                return;
            this.logChannel.LogMessage(message, LoggingLevel.Warning);
            SaveFile();
        }
        public void Warn(string message, params object[] parameters)
        {
            if (DesignMode.DesignModeEnabled || this.logChannel == null)
                return;
            this.logChannel.LogMessage(string.Format(message, parameters), LoggingLevel.Warning);
            SaveFile();
        }

        private async Task RegisterUnhandledErrorHandler()
        {
            logUploadFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("MyLogFile",
                CreationCollisionOption.OpenIfExists);

            CoreApplication.UnhandledErrorDetected += CoreApplication_UnhandledErrorDetected;

        }

        /// <summary> 
        /// Any  uncaught exceptions are thrown to here 
        /// </summary> 
        /// <param name="sender"></param> 
        /// <param name="e"></param> 
        private void CoreApplication_UnhandledErrorDetected(object sender, UnhandledErrorDetectedEventArgs e)
        {
            try
            {
                // logChannel.LogMessage("Caught the exception");
                e.UnhandledError.Propagate();

            }
            catch (Exception ex)
            {
                //logChannel.LogMessage(string.Format("UnhandledErro: 0x{0:X})", ex.HResult), LoggingLevel.Critical); 
                logChannel.LogMessage(string.Format("Effor Message: {0}", ex.Message));




                // throw; 
            }
            SaveFile();
        }

        private void SaveFile()
        {
            if (logSession != null)
            {
                if (_errorHandlerTask != null)
                    return;
                //lock (LockObject)
                //{
                //var filename = DateTime.Now.ToString("yyyyMMdd-HHmmssTzz") + ".etl";
                _errorHandlerTask = Task.Run(async () =>
                      {
                          var filename = DateTime.Now.ToString("yyyyMMdd") + ".etl";
                          var logSaveTast =await logSession
                              .SaveToFileAsync(logUploadFolder, filename);//.AsTask();
                         // logSaveTast.Wait();
                          _errorHandlerTask = null;
                      });
                //}
            }
        }

        /// <summary> 
        /// Deelete the files based on the days mentioned 
        /// </summary> 

        public async Task Deletefile()
        {
            try
            {

                var logFiles = await logUploadFolder.GetFilesAsync();

                foreach (var logFile in logFiles)
                {
                    if ((DateTime.Now - logFile.DateCreated).Days > DAYS_TO_DELETE)
                    {
                        await logFile.DeleteAsync();
                    }


                }
            }
            catch (Exception ex)
            {
                logChannel.LogMessage(ex.Message);

            }
        }

    }
}
